Amazon RekognitionのImage Moderationを活用してTwitterの不適切な画像を収集する
「お前は何をやっているんだ」という意見は正しいと思います。
はじめに
先日Amazon RekognitionにImage Moderation機能が追加されました。
今回はこの機能を使って、TwitterのPublic timelineから、不適切と思われる画像を収集してみます。
やってみた
スクリプト本体はAWS SDK for Goを使用しました。新機能を使う前に最新版を取得しておきます。
$ go get -u github.com/aws/aws-sdk-go/
また、TwitterのPublic timelineの収集にはChimeraCoder/anacondaライブラリを使用しました。
$ go get -u github.com/ChimeraCoder/anaconda/
スクリプト
スクリプトの内容は以下の通りです。詳細はコメントとして書きました。Golangとしてはもっと綺麗な書き方があるんだと思いますが、その辺はご容赦ください。もっと素敵なコードが書けるようになりたいものです。
package main import ( "bytes" "fmt" "io/ioutil" "net/http" "os" "path/filepath" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/rekognition" "github.com/ChimeraCoder/anaconda" ) func main() { // Twitter認証情報をセット consumerKey := os.Getenv("TWITTER_CONSUMER_KEY") consumerSecret := os.Getenv("TWITTER_CONSUMER_SECRET") AccessToken := os.Getenv("TWITTER_ACCESS_TOKEN") AccessTokenSecret := os.Getenv("TWITTER_ACCESS_TOKEN_SECRET") // Twitter認証 anaconda.SetConsumerKey(consumerKey) anaconda.SetConsumerSecret(consumerSecret) api := anaconda.NewTwitterApi(AccessToken, AccessTokenSecret) // TwitterのPublicStream(statuses/sample)を取得 twitterStream := api.PublicStreamSample(nil) for { // データを取得 data := <-twitterStream.C switch tweet := data.(type) { // Tweetの場合 case anaconda.Tweet: // 画像URLを格納する配列を定義 var url []string // 画像URLを配列に格納 m := tweet.ExtendedEntities.Media for i := 0; i < len(m); i++ { url = append(url, m[i].Media_url) } for i := 0; i < len(url); i++ { // 画像を取得 getImage(url[i]) } default: } } } func getImage(url string) { // 画像ファイルのURLに:largeを追加 var buffer bytes.Buffer buffer.WriteString(url) buffer.WriteString(":large") // largeな画像ファイルを取得 image, err := http.Get(buffer.String()) if err != nil { fmt.Println(err.Error()) return } defer image.Body.Close() // 画像ファイルのデータを全て読み込み bytes, err := ioutil.ReadAll(image.Body) if err != nil { fmt.Println(err.Error()) return } // セッション作成 sess := session.Must(session.NewSession()) // Rekognitionクライアントを作成 svc := rekognition.New(sess, aws.NewConfig().WithRegion("us-east-1")) // svc.DetectModerationLabelsに渡すパラメータを設定 params := &rekognition.DetectModerationLabelsInput{ Image: &rekognition.Image{ Bytes: bytes, }, // Confidenceが70%以上 MinConfidence: aws.Float64(0.7), } // svc.DetectModerationLabelsを実行 resp, err := svc.DetectModerationLabels(params) if err != nil { fmt.Println(err.Error()) return } // 対象であれば処理継続 if len(resp.ModerationLabels) != 0 { // URLからファイル名を取得 filename := filepath.Base(url) if err != nil { fmt.Println(err.Error()) return } // ファイルを作成 file, err := os.Create(filename) if err != nil { fmt.Println(err.Error()) return } defer file.Close() // ファイルを書き込んで保存 file.Write(bytes) // 保存した情報を出力 fmt.Println(resp.ModerationLabels) fmt.Println("Save " + filename + ".") } return }
作成したスクリプトはgo fmtで整形します。
$ go fmt getpic.go
そしてbuildします。
$ go build
バイナリが出来上がります。
$ ls getpic getpic.go
実行結果
実行すると以下のように出力されます。
$ ./getpic [{ Confidence: 53.97080612182617, Name: "Explicit Nudity", ParentName: "" } { Confidence: 53.97080612182617, Name: "Graphic Male Nudity", ParentName: "Explicit Nudity" }] Save C-KFERyXkAE1oGP.jpg. [{ Confidence: 57.758872985839844, Name: "Suggestive", ParentName: "" } { Confidence: 57.758872985839844, Name: "Female Swimwear Or Underwear", ParentName: "Suggestive" }] Save C-H_9B1XkAIKTdK.jpg. ....snip....
そして保存された画像がこちら...なのですが、ちょっとお見せできないのでモザイクかけました。
というような使い方もできますね!
さいごに
Image Moderationは一般的にはフィルタリングするために使われますが、こういった使い方もできます。今回は単純にConfidenceが70%以上の画像を取得しましたが、ParentNameとNameを判別することで、特定のカテゴリと判定された画像のみを選別することも可能です。
以上、ちょっと変わったユースケースでした。